#pragma once
#include <vector>
#include <map>
#include <memory>
#include <functional>
#include <sys/epoll.h>
#include <mutex>


class Acceptor;
class TcpConnection;
/**
 * @author: hsl
 * @date: 2025/8/29
 * @description: EventLoop
 */

using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
using TcpConnectionCallback = std::function<void(const TcpConnectionPtr&)>;

class EventLoop{
    using Functor = std::function<void()>;
    private:
    int _epfd;//epoll_create产生的的文件描述符
    std::vector<struct epoll_event> _evtList;//存放满足条件的文件描述符的数据结构
    bool _isLooping;//标识循环是否在运行的标志
    Acceptor& _acceptor;
    std::map<int,TcpConnectionPtr> _conns;//fd->TcpConnection的映射
    TcpConnectionCallback _onNewConnectionCallback;//新连接的回调函数
    TcpConnectionCallback _onMessageCallback;//读事件的回调函数
    TcpConnectionCallback _onCloseCallback;//关闭事件的回调函数

    int _evtfd;//用于唤醒epoll_wait的文件描述符
    std::vector<Functor> _pendingTasks;//存放EventLoop待发送的数据
    std::mutex _pendingTasksMutex;//保护_pendingTasks的互斥锁

public:
    EventLoop(Acceptor& acceptor);
    ~EventLoop();
    void loop();
    void unLoop();
    void setNewConnectionCallback(TcpConnectionCallback &&cb);
    void setMessageCallback(TcpConnectionCallback &&cb);
    void setCloseCallback(TcpConnectionCallback &&cb);

    void runInLoop(Functor&& cb);//将任务添加到待发送_pendingTasks中
private:

    //创建epoll文件描述符
    int createEpollFd();
    //等待epoll事件的触发
    void waitEpollFd();
    //等待epoll事件的触发
    void addEpollReadFd(int fd);
    //等待epoll事件的触发
    void removeEpollReadFd(int fd);

    void handleNewConnection();
    void handleMessage(int fd);


    void handleRead();//读取_evtfd中的计数值，清零_evtfd
    void doPendingFunctors();//执行待发送的任务
    void wakeup();//唤醒epoll_wait
    
    int createEventFd();//创建用于唤醒epoll_wait的文件描述符
};